package cfh.spring.data.jpademo;

import cfh.spring.data.jpademo.model.Coffee;
import cfh.spring.data.jpademo.model.CoffeeOrder;
import cfh.spring.data.jpademo.model.OrderState;
import cfh.spring.data.jpademo.repository.PagingAndSorting.CoffeeOrderPagingAndSortingRepository;
import cfh.spring.data.jpademo.repository.PagingAndSorting.CoffeePagingAndSortingRepository;
import cfh.spring.data.jpademo.repository.crud.CoffeeCrudRepository;
import cfh.spring.data.jpademo.repository.crud.CoffeeOrderCrudRepository;
import lombok.extern.slf4j.Slf4j;
import org.joda.money.CurrencyUnit;
import org.joda.money.Money;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Sort;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 测试类
 *
 * @author chenfh
 * date 2019/7/30
 */

@SpringBootTest
@RunWith(SpringRunner.class)
@Slf4j
public class JpaDemoTestApplication {

    @Autowired
    private CoffeeCrudRepository coffeeCrudRepository;
    @Autowired
    private CoffeeOrderCrudRepository coffeeOrderCrudRepository;

    @Autowired
    private CoffeePagingAndSortingRepository coffeePagingAndSortingRepository;

    @Autowired
    private CoffeeOrderPagingAndSortingRepository coffeeOrderPagingAndSortingRepository;


    public void iInitOrders() {
        Coffee espresso = Coffee.builder().name("espresso")
                .price(Money.of(CurrencyUnit.of("CNY"), 20.0))
                .build();
        coffeeCrudRepository.save(espresso);
        log.error("Coffee1: {}", espresso);

        Coffee latte = Coffee.builder().name("latte")
                .price(Money.of(CurrencyUnit.of("CNY"), 30.0))
                .build();
        coffeeCrudRepository.save(latte);
        log.error("Coffee2: {}", latte);

        CoffeeOrder order = CoffeeOrder.builder()
                .customer("Li Lei")
                .items(Collections.singletonList(espresso))
                .state(OrderState.INIT)
                .build();
        coffeeOrderCrudRepository.save(order);
        log.error("Order1: {}", order);

        order = CoffeeOrder.builder()
                .customer("Li Lei")
                .items(Arrays.asList(espresso, latte))
                .state(OrderState.INIT)
                .build();
        coffeeOrderCrudRepository.save(order);
        log.error("Order2: {}", order);
    }

    private void findOrders() {
        coffeePagingAndSortingRepository
                .findAll(Sort.by(Sort.Direction.DESC, "id"))
                .forEach(c -> log.error("Loading {}", c));

        List<CoffeeOrder> list = coffeeOrderPagingAndSortingRepository
                .findTop3ByOrderByUpdateTimeDescIdAsc();
        log.error("findTop3ByOrderByUpdateTimeDescIdAsc: {}", getJoinedOrderId(list));

        list = coffeeOrderPagingAndSortingRepository.findByCustomerOrderById("Li Lei");
        log.error("findByCustomerOrderById: {}", getJoinedOrderId(list));

        // 不开启事务会因为没Session而报LazyInitializationException
        list.forEach(o -> {
            log.error("Order {}", o.getId());
            o.getItems().forEach(i -> log.error("  Item {}", i));
        });

        list = coffeeOrderPagingAndSortingRepository.findByItemsName("latte");
        log.error("findByItems_Name: {}", getJoinedOrderId(list));
    }
    @Test
    @Transactional
    public void testTwoOpera() {
        iInitOrders();
        findOrders();
    }

    private String getJoinedOrderId(List<CoffeeOrder> list) {
        return list.stream().map(o -> o.getId().toString())
                .collect(Collectors.joining(","));
    }
}
